package cmdwin;

import htmlview.HtmlTextPane;

import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.StringReader;
import java.net.URL;
import java.net.URLConnection;
import java.util.Hashtable;
import java.util.Properties;

import javax.swing.JFrame;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.JViewport;
import javax.swing.KeyStroke;
import javax.swing.UIManager;
import javax.swing.text.AbstractDocument;
import javax.swing.text.Document;
import javax.swing.text.EditorKit;
import javax.swing.text.SimpleAttributeSet;

import textcvt.RuleFilterReader;
import textcvt.RuleScript;
import textcvt.SimpleRuleBasedFilter;

public class CommandWindow extends JFrame {
	
	private javax.swing.JMenuBar jMenuBar;
	private javax.swing.JMenu jMenuFile;
	private javax.swing.JMenu jMenuView;
	private javax.swing.JMenuItem jMenuItemZoomIn = null;
	private javax.swing.JMenuItem jMenuItemZoomOut = null;

    private javax.swing.JMenuItem jMenuItemOpen;
    private javax.swing.JSeparator jSeparator1;
    private javax.swing.JMenuItem jMenuItemExit;
    
    private javax.swing.JMenu jMenuHelp;
    private javax.swing.JMenuItem jMenuAbout;
    
    private JPanel viewPanel ;
    private HtmlTextPane view;
    private JTextField cmdText;
     
    private Context context = new Context(this);
    
    static Hashtable<String, ICommand> cmdrun = new Hashtable<String, ICommand>();
    static{   
    	cmdrun.put("open", new CommandOpen());
    	cmdrun.put("dir", new CommandDIR());
    	cmdrun.put("show", new CommandShow());
    	cmdrun.put("content-type", new CommandConentType());
    	cmdrun.put("filter", new CommandFilter());
    	//cmdrun.put("cd", new CommandCD(context));
    }
        
    private ActionListener menuActionListener=new ActionListener(){
		public void actionPerformed(ActionEvent e) {
			Object src=e.getSource();
			if(src==jMenuItemOpen){
				cmdText.setText("open:");
				cmdText.setVisible(true);
				cmdText.requestFocus();
				validate();
				return;
			}
			if(src==jMenuItemExit){
				dispose();
				return;
			}
			if(src==jMenuAbout){
				String message="<html>Author: Bing <BR />Email: yexinbing@yahoo.com.cn</html>";
				JOptionPane.showMessageDialog(CommandWindow.this, message);
				return;
			}
		}    	
    }; 
    


	public CommandWindow() {
		initComponents();
		
		final Properties prop = context.loadProperties("init");
		java.awt.EventQueue.invokeLater(new Runnable(){
			public void run() {
				String cmd_count = prop.getProperty("cmd_count").trim();
				int count = 0;
				if(cmd_count!=null && cmd_count.length()>0){
					count = Integer.parseInt(cmd_count);
				}		
				for(int i=0;i<count;i++){
					String cmd = prop.getProperty("cmd" + i).trim();
					context.proccessCommand(cmd);
				}				
			}			
		});

	}
	
	
	private void initComponents() {
		
		//menu ||
        jMenuBar = new javax.swing.JMenuBar();
        
        jMenuFile = new javax.swing.JMenu("File");
        
        jMenuItemOpen = new javax.swing.JMenuItem();
        jSeparator1 = new javax.swing.JSeparator();
        jMenuItemExit = new javax.swing.JMenuItem();
        jMenuHelp = new javax.swing.JMenu();
        jMenuAbout = new javax.swing.JMenuItem();
 
        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);

        
        jMenuItemOpen.setText("Open");
        jMenuItemOpen.addActionListener(menuActionListener);
        jMenuItemOpen.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_O, InputEvent.CTRL_MASK));
        
                
        jMenuFile.add(jMenuItemOpen);

        jMenuFile.add(jSeparator1);

        jMenuItemExit.setText("Exit");
        jMenuFile.add(jMenuItemExit);
        jMenuItemExit.addActionListener(menuActionListener);
        jMenuBar.add(jMenuFile);
        
        //menu: view
        jMenuView = new javax.swing.JMenu("View");
        jMenuBar.add(jMenuView);
        
        jMenuItemZoomIn = new JMenuItem("Zoom In");
        jMenuItemZoomIn.addActionListener(menuActionListener);   
        jMenuItemZoomIn.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_EQUALS, InputEvent.CTRL_MASK ));
        jMenuView.add(jMenuItemZoomIn);
        
        jMenuItemZoomOut = new JMenuItem("Zoom out");
        jMenuItemZoomOut.addActionListener(menuActionListener);  
        jMenuItemZoomOut.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_MINUS, InputEvent.CTRL_MASK ));
        jMenuView.add(jMenuItemZoomOut);
                
        jMenuHelp.setText("Help");

        jMenuAbout.setText("About");
        jMenuAbout.addActionListener(menuActionListener);
        jMenuHelp.add(jMenuAbout);

        jMenuBar.add(jMenuHelp);

        setJMenuBar(jMenuBar);
        
        setLayout(new BorderLayout());
        
        viewPanel = new JPanel(new CardLayout());
        add(viewPanel,"Center");
        
    	JScrollPane scroller = new JScrollPane();
    	JViewport viewerContainer = scroller.getViewport();
    	view = new HtmlTextPane();
    	viewerContainer.add(view);
    	
    	viewPanel.add(scroller,"0");
    	    	
    	cmdText = new JTextField();
    	add(cmdText,"South");
    	cmdText.setVisible(false);
    	
        cmdText.addKeyListener(new KeyListener(){
			public void keyPressed(KeyEvent e) {
				switch(e.getKeyChar()){
				case KeyEvent.VK_ENTER:
					context.proccessCommand(cmdText.getText());
					break;
				case KeyEvent.VK_ESCAPE:
					break;
				default:
					return;
				}
				cmdText.setVisible(false);
				validate();
			}
			public void keyReleased(KeyEvent e) {
			}
			public void keyTyped(KeyEvent e) {
			}
        });
        
	}
	
    private void zoomIn(){
        SimpleAttributeSet attrset = new SimpleAttributeSet();
//        StyleConstants.setFontSize(attrset, ++fontSize);
        //StyleConstants.setBold(attrset, true);
//    	view.getDocument().setCharacterAttributes(0, view.getDocument().getLength(),attrset, false);
    }
    
    private void zoomOut(){
        SimpleAttributeSet attrset = new SimpleAttributeSet();
//      StyleConstants.setFontSize(attrset, --fontSize);
//    	view.getDocument().setCharacterAttributes(0, view.getDocument().getLength(),attrset, false);  	
    }
				
	public Context getContext(){
		return context;
	}
	
	public HtmlTextPane getView(){
		return this.view;
	}

	private static void installLnF() {
		try {
			String lnfClassname = null;
			if (lnfClassname == null)
				lnfClassname = UIManager.getCrossPlatformLookAndFeelClassName();
			UIManager.setLookAndFeel(lnfClassname);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}


	public static void main(String[] args) {
		installLnF();
		java.awt.EventQueue.invokeLater(new Runnable() {
			public void run() {
				CommandWindow frame = new CommandWindow();	
				frame.setDefaultCloseOperation(CommandWindow.EXIT_ON_CLOSE);
				frame.setTitle("Command Window");
				frame.setBounds(150, 100, 800, 600);
				frame.getContentPane().setPreferredSize(frame.getSize());
				frame.setVisible(true);
			}
		});
	}
	
	private static class CommandOpen implements ICommand{
		private boolean isFilePath(String urlstr){
			if(urlstr.charAt(0)=='/' || urlstr.charAt(0)==File.separatorChar)
				return true;
			if(urlstr.charAt(1)==':'){
				char c = Character.toUpperCase(urlstr.charAt(0));
				if(c >= 'A' && c<='Z'){
					return true;
				}
			}	
			return false;
		}
		
		private String getCharset(String contentType){			
			if(contentType==null||contentType.isEmpty())
				return null;
			int p = contentType.indexOf(';');
			String params = contentType.substring(p+1).trim();
			if(params.isEmpty())
				return null;
			String[] parr = params.split("=");
			return parr.length>1?parr[1].trim():null;
		}
		
		private static CharSequence getInput(Reader reader){
			StringBuilder sb = new StringBuilder(4096);
			long t1 = System.currentTimeMillis();
			int c;
			try {
				while((c=reader.read())!=-1){
					sb.append((char)c);
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
			System.out.println("download cost:" + (System.currentTimeMillis()-t1));
			return sb;
		} 
		
		public void execute(Context cxt, String[] params) throws Exception {
			RuleFilterReader filterReader = null;
			
			String urlstr = params[0];
			String filter = (String)cxt.getUserData(Context.USERDATA_FILTER);			
						
			if(isFilePath(urlstr)){
				StringBuilder sb = new StringBuilder(urlstr.length() + 16);		
				sb.append("file:///").append(urlstr);
				for(int i=0; i<sb.length(); i++){
					if(sb.charAt(i)==File.separatorChar)
						sb.setCharAt(i, '/');
				}
				urlstr = sb.toString();
			}
			
			if(!urlstr.startsWith("file:")){
				if(!urlstr.startsWith("http://"))
					urlstr = "http://" + urlstr;
			}
			
			CharSequence source = null;
		
			URL url = new URL(urlstr);			
			URLConnection conn = url.openConnection();
			InputStream inStream = new BufferedInputStream(conn.getInputStream());
			String enc = getCharset(conn.getContentType());
			
			Reader reader = enc==null?new InputStreamReader(inStream):new InputStreamReader(inStream,enc);
			
			source = getInput(reader);
			
			try {
				reader.close();
			} catch (Exception e1) {
				e1.printStackTrace();
			}
			
			if(filter!=null){
				SimpleRuleBasedFilter rbf = new SimpleRuleBasedFilter(source, new RuleScript(cxt.getCfgResource(filter)));
				source = rbf.filter();
			}
			
			cxt.setUserData(Context.USERDATA_DOC, source);
	    	cxt.getCommand("show").execute(cxt, new String[0]);    
		}
	}
	
	private static class CommandDIR implements ICommand{
		public CommandDIR(){
		}
		public void execute(Context cxt, String[] params) {
			if(params==null || params.length<1)
				return;
			
			String dir = null;
			if(params[0]==null || (dir=params[0].trim()).isEmpty()){
				dir = "";
			}
			File file = new File(dir);
			File[] files = file.listFiles();
			
		}
	}
	
	private static class CommandShow implements ICommand{
		public void execute(Context cxt, String[] params) throws Exception {
			CharSequence src = null;
			if(params.length>0){
				src = params[0];
			}else{
				src = (CharSequence)cxt.getUserData(Context.USERDATA_DOC);
			}
			final HtmlTextPane view = cxt.getCommandWindow().getView();			
			StringReader reader = new StringReader(src.toString());
	    	try {
	    		EditorKit kit = view.getEditorKit();				
	    		Document doc = kit.createDefaultDocument();
	    		((AbstractDocument)doc).getDocumentProperties().put("IgnoreCharsetDirective", new Boolean(true));	    		
	    		kit.read(reader, doc, 0);
				view.setDocument(doc);   		
				
			} catch (Exception e) {
				e.printStackTrace();
			}  
		}		
	}
	
	private static class CommandConentType implements ICommand{
		public void execute(Context cxt, String[] params) throws Exception {
			String type = params.length==0?"text/plain":params[0];
			cxt.getCommandWindow().getView().setContentType(type);	
		}		
	}
	
	private static class CommandFilter implements ICommand{
		public void execute(Context cxt, String[] params) throws Exception {
			String path = params.length==0?"/config/filter.xml":params[0];
			cxt.setUserData(Context.USERDATA_FILTER, path);	
		}		
	}
	
}
